use crate::{Address, Byte, EmulatorError, Result, memory::MemoryBus};
use super::StatusRegister;

/// 6502 CPU 模拟核心
pub struct Cpu {
    /// 程序计数器
    pub pc: Address,
    /// 栈指针
    pub sp: Byte,
    /// 累加器
    pub a: Byte,
    /// X 索引寄存器
    pub x: Byte,
    /// Y 索引寄存器
    pub y: Byte,
    /// 状态寄存器
    pub status: StatusRegister,
    /// 内存总线引用
    pub memory_bus: MemoryBus,
    /// 当前指令剩余的时钟周期
    pub cycles_remaining: u32,
}

impl Cpu {
    pub fn new(memory_bus: MemoryBus) -> Self {
        Cpu {
            pc: 0,
            sp: 0xFD, // 6502 栈指针初始值
            a: 0,
            x: 0,
            y: 0,
            status: StatusRegister::new(),
            memory_bus,
            cycles_remaining: 0,
        }
    }

    /// 重置 CPU 到初始状态
    pub fn reset(&mut self) -> Result<()> {
        self.pc = self.read_word(0xFFFC)?; // 重置向量地址
        self.sp = 0xFD;
        self.a = 0;
        self.x = 0;
        self.y = 0;
        self.status = StatusRegister::new();
        self.cycles_remaining = 8; // 重置需要 8 个时钟周期
        
        Ok(())
    }

    /// 执行一个时钟周期
    pub fn tick(&mut self) -> Result<()> {
        if self.cycles_remaining == 0 {
            self.execute_instruction()?;
        }
        
        if self.cycles_remaining > 0 {
            self.cycles_remaining -= 1;
        }
        
        Ok(())
    }

    /// 执行当前指令
    fn execute_instruction(&mut self) -> Result<()> {
        let opcode = self.read_byte(self.pc)?;
        self.pc = self.pc.wrapping_add(1);
        
        // 根据操作码执行指令
        match opcode {
            // 这里将实现所有 6502 指令
            // 暂时只实现 NOP 指令作为示例
            0xEA => { // NOP
                self.cycles_remaining = 2;
            }
            _ => {
                return Err(EmulatorError::InvalidOpcode(opcode));
            }
        }
        
        Ok(())
    }

    /// 从内存读取一个字节
    fn read_byte(&mut self, address: Address) -> Result<Byte> {
        self.memory_bus.read(address)
    }

    /// 从内存读取一个字（小端序）
    fn read_word(&mut self, address: Address) -> Result<Address> {
        let low = self.read_byte(address)? as Address;
        let high = self.read_byte(address.wrapping_add(1))? as Address;
        Ok((high << 8) | low)
    }

    /// 向内存写入一个字节
    fn write_byte(&mut self, address: Address, value: Byte) -> Result<()> {
        self.memory_bus.write(address, value)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::memory::Ram;

    #[test]
    fn test_cpu_initialization() {
        let ram = Ram::new(0x10000);
        let memory_bus = MemoryBus::new(ram);
        let cpu = Cpu::new(memory_bus);
        
        assert_eq!(cpu.pc, 0);
        assert_eq!(cpu.sp, 0xFD);
        assert_eq!(cpu.a, 0);
        assert_eq!(cpu.x, 0);
        assert_eq!(cpu.y, 0);
    }
}